#include "NxHttp.h"
#include "curl/curl.h"
#include <iostream>

size_t NJGIS::SERVICE::NjHttpHelper::req_reply( void *ptr, size_t size, size_t nmemb, void *stream )
{ 
	std::string *str = (std::string*)stream;  
	(*str).append((char*)ptr, size*nmemb);
	return size * nmemb;  
}

int NJGIS::SERVICE::NjHttpHelper::init()
{
	curl_global_init(CURL_GLOBAL_ALL);
	return 1;
}

int NJGIS::SERVICE::NjHttpHelper::request_get_sync( const char* url, std::string &responsebody )
{
	// init curl  
	CURL *curl = curl_easy_init();  
	// res code  
	CURLcode res;
	// head
	std::string head;

	if (curl)  
	{  
		// set params  
		curl_easy_setopt(curl, CURLOPT_URL, url); // url  
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https  
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false  
		// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NJGIS::SERVICE::NjHttpHelper::req_reply);  
		curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&head); 
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&responsebody);  
		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); // set transport and time out time  
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
		// start req  
		res = curl_easy_perform(curl);  
	}  
	// release curl  
	curl_easy_cleanup(curl);

	return 1;
}

int NJGIS::SERVICE::NjHttpHelper::request_post_withform_sync( const char* url, NJGIS::SERVICE::INjFormParam* &list_form, NJGIS::SERVICE::INjLocalFiles* &list_files, std::string &responsebody )
{
	CURL *curl;
	CURLcode res;

	std::string head;
 
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Expect:";
 
	curl_global_init(CURL_GLOBAL_ALL);
 
	/* Fill in the file upload field */ 
	for (int i = 0 ; i < list_files->getCount(); i++)
	{
		curl_formadd(&formpost,
			&lastptr,
			CURLFORM_COPYNAME, list_files->getName(i),
			CURLFORM_FILE, list_files->getPath(i),
			CURLFORM_END);
	}
 
 
	/* Fill in the submit field too, even if this is rarely needed */ 
	for (int i = 0; i < list_form->getCount(); i++)
	{
		curl_formadd(&formpost,
			&lastptr,
			CURLFORM_COPYNAME, list_form->getKey(i),
			CURLFORM_COPYCONTENTS, list_form->getValue(i),
			CURLFORM_END);
	}
 
	curl = curl_easy_init();
	/* initialize custom header list (stating that Expect: 100-continue is not
		wanted */ 
	headerlist = curl_slist_append(headerlist, buf);
	if(curl) {
		/* what URL that receives this POST */ 
		curl_easy_setopt(curl, CURLOPT_URL, url);
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

		curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NJGIS::SERVICE::NjHttpHelper::req_reply);  
		curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&head); 
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&responsebody);  
		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); // set transport and time out time  
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
 
		/* Perform the request, res will get the return code */ 
		res = curl_easy_perform(curl);
		/* Check for errors */ 
		if(res != CURLE_OK)
		{
			fprintf(stderr, "curl_easy_perform() failed: %s\n",
				curl_easy_strerror(res));
		}
 
		/* always cleanup */ 
		curl_easy_cleanup(curl);
 
		/* then cleanup the formpost chain */ 
		curl_formfree(formpost);
		/* free slist */ 
		curl_slist_free_all (headerlist);
	}

	return 1;
}

int NJGIS::SERVICE::NjHttpHelper::request_put_sync( const char* url, std::string &responsebody )
{
	// init curl  
	CURL *curl = curl_easy_init();  
	// res code  
	CURLcode res;
	// head
	std::string head;

	if (curl)  
	{  
		// set params  
		curl_easy_setopt(curl, CURLOPT_URL, url); // url  
		curl_easy_setopt(curl, CURLOPT_PUT, 1L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https  
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false  
		// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NJGIS::SERVICE::NjHttpHelper::req_reply);  
		curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&head); 
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&responsebody);  
		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); // set transport and time out time  
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
		// start req  
		res = curl_easy_perform(curl);  
	}  
	// release curl  
	curl_easy_cleanup(curl);

	return 1;
}

int NJGIS::SERVICE::NjHttpHelper::request_get_json_sync( const char* url, Json::Value &value )
{
	std::string body;
	int res = NJGIS::SERVICE::NjHttpHelper::request_get_sync(url, body);
	Json::Reader reader;
	if (reader.parse(body, value))
	{  
		return 1;
	}
	else
	{
		return -2;
	}
}

int NJGIS::SERVICE::NjHttpHelper::request_post_withform_json_sync( const char* url, INjFormParam* &list_form, INjLocalFiles* &list_files, Json::Value &value )
{
	std::string body;
	int res = NJGIS::SERVICE::NjHttpHelper::request_post_withform_sync(url, list_form, list_files, body);
	Json::Reader reader;
	if (reader.parse(body, value))
	{  
		return 1;
	}
	else
	{
		return -2;
	}

}

int NJGIS::SERVICE::NjHttpHelper::request_put_json_sync( const char* url, Json::Value &value )
{
	std::string body;
	int res = NJGIS::SERVICE::NjHttpHelper::request_put_sync(url, body);
	Json::Reader reader;
	if (reader.parse(body, value))
	{  
		return 1;
	}
	else
	{
		return -2;
	}
}

int NJGIS::SERVICE::NjHttpHelper::download( const char* url, const char* path )
{
	FILE* fp = fopen(path, "wb");  
	if (!fp) {  
		printf("!!! Failed to create file on the disk\n");  
		return false;  
	}  

	// init curl  
	CURL *curl = curl_easy_init();  
	curl_easy_setopt(curl, CURLOPT_URL, url);  
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);  
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NJGIS::SERVICE::NjHttpHelper::req_reply_file);  
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  

	CURLcode rc = curl_easy_perform(curl);  
	if (rc) {   
		return -1;  
	}  

	long res_code = 0;  
	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code);  
	if (!((res_code == 200 || res_code == 201) && rc != CURLE_ABORTED_BY_CALLBACK)) {   
		return -2;  
	}  

	curl_easy_cleanup(curl);  
	fclose(fp);  

	return 1;  
}

size_t NJGIS::SERVICE::NjHttpHelper::req_reply_file( void *ptr, size_t size, size_t nmemb, FILE *stream )
{
	return fwrite(ptr, size, nmemb, stream);  
}
